import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.logging.Logger;
import org.rsbot.event.listeners.PaintListener;
import org.rsbot.event.listeners.TextPaintListener;
import org.rsbot.script.Script;
import org.rsbot.script.ScriptManifest;
import org.rsbot.script.methods.Calculations;
import org.rsbot.script.methods.Game;
import org.rsbot.script.methods.Walking;
import org.rsbot.script.wrappers.RSPath;
import org.rsbot.script.wrappers.RSPlayer;
import org.rsbot.script.wrappers.RSTile;
import org.rsbot.util.StringUtil;

@ScriptManifest(authors={"Jacmob"}, keywords={"Development"}, name="Map Explorer", version=0.2D, description="Provides map info for developers.")
public class MapExplorer extends Script
  implements TextPaintListener, PaintListener, MouseListener
{
  public static final Color TILE_CLEAR_FILL = new Color(0, 255, 0, 100);
  public static final Color TILE_BLOCKED_FILL = new Color(255, 0, 0, 100);
  public static final Color PATH_FILL = new Color(0, 0, 255, 100);
  public static final int WALL_NORTH_WEST = 1;
  public static final int WALL_NORTH = 2;
  public static final int WALL_NORTH_EAST = 4;
  public static final int WALL_EAST = 8;
  public static final int WALL_SOUTH_EAST = 16;
  public static final int WALL_SOUTH = 32;
  public static final int WALL_SOUTH_WEST = 64;
  public static final int WALL_WEST = 128;
  public static final int BLOCKED = 256;
  public static final RSTile[] EMPTY_PATH = new RSTile[0];
  private final MapExplorer.AStar pf;
  private volatile RSTile current;
  private volatile RSTile[] path;
  RSPath walk_path;

  public MapExplorer()
  {
    this.pf = new MapExplorer.AStar();

    this.current = new RSTile(0, 0);
    this.path = EMPTY_PATH;
  }

  public boolean onStart()
  {
    this.walk_path = this.walking.getPath(new RSTile(3165, 3484));
    this.pf.init(this.game, this.walking);
    return true;
  }

  public int loop() {
    if (this.calc.distanceTo(this.current) > 100) {
      this.current = getMyPlayer().getLocation();
    }
    this.walk_path.traverse();
    return 100;
  }

  public void mouseClicked(MouseEvent paramMouseEvent)
  {
  }

  public void mousePressed(MouseEvent paramMouseEvent)
  {
  }

  public void mouseReleased(MouseEvent paramMouseEvent) {
    Point localPoint1 = paramMouseEvent.getPoint();
    if ((localPoint1.x > 0) && (localPoint1.x < this.game.getWidth())) {
      Object localObject1 = null;
      Object localObject2;
      for (int i = 0; i < 104; i++) {
        for (int j = 0; j < 104; j++) {
          localObject2 = new RSTile(i + this.game.getBaseX(), j + this.game.getBaseY());
          Point localPoint2 = this.calc.tileToScreen((RSTile)localObject2);
          if ((localPoint2.x != -1) && (localPoint2.y != -1)) {
            if (localObject1 == null) {
              localObject1 = localObject2;
            }
            if (this.calc.tileToScreen(localObject1).distance(localPoint1) > this.calc.tileToScreen((RSTile)localObject2).distance(localPoint1)) {
              localObject1 = localObject2;
            }
          }
        }
      }
      if (localObject1 != null) {
        this.current = localObject1;
        long l = System.currentTimeMillis();
        localObject2 = this.pf.findPath(getMyPlayer().getLocation(), localObject1);
        if (localObject2 == null) {
          this.log.info("unreachable");
          this.path = EMPTY_PATH;
        } else {
          this.log.info(new StringBuilder().append("path calculated in ").append(System.currentTimeMillis() - l).append("ms").toString());
          this.path = ((RSTile)localObject2);
        }
      }
    }
  }

  public void mouseEntered(MouseEvent paramMouseEvent)
  {
  }

  public void mouseExited(MouseEvent paramMouseEvent)
  {
  }

  public void onRepaint(Graphics paramGraphics)
  {
    ((Graphics2D)paramGraphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    RSTile localRSTile1 = this.walking.getCollisionOffset(this.game.getPlane());
    int i = this.walking.getCollisionFlags(this.game.getPlane())[(this.current.getX() - this.game.getBaseX() - localRSTile1.getX())][(this.current.getY() - this.game.getBaseY() - localRSTile1.getY())];
    if ((i & 0x100) == 0)
      highlight(paramGraphics, this.current, TILE_CLEAR_FILL);
    else {
      highlight(paramGraphics, this.current, TILE_BLOCKED_FILL);
    }
    for (RSTile localRSTile2 : this.path)
      if (!localRSTile2.equals(this.current))
        highlight(paramGraphics, localRSTile2, PATH_FILL);
  }

  public int drawLine(Graphics paramGraphics, int paramInt)
  {
    RSTile localRSTile = this.walking.getCollisionOffset(this.game.getPlane());
    int i = this.walking.getCollisionFlags(this.game.getPlane())[(this.current.getX() - this.game.getBaseX() - localRSTile.getX())][(this.current.getY() - this.game.getBaseY() - localRSTile.getY())];
    StringUtil.drawLine(paramGraphics, paramInt++, new StringBuilder().append("Base: (").append(this.game.getBaseX()).append(",").append(this.game.getBaseY()).append(")").toString());
    StringUtil.drawLine(paramGraphics, paramInt++, new StringBuilder().append("Offset: ").append(localRSTile).toString());
    StringUtil.drawLine(paramGraphics, paramInt++, new StringBuilder().append("Target: ").append((i & 0x100) == 0 ? "Clear " : "[red]Blocked ").append(this.current).toString());
    StringUtil.drawLine(paramGraphics, paramInt++, new StringBuilder().append("Flags: B'").append(getBinaryString(i)).append("' 0x").append(Integer.toHexString(i)).toString());
    drawBorderFlag(paramGraphics, paramInt++, i, "N", 2);
    drawBorderFlag(paramGraphics, paramInt++, i, "NE", 4);
    drawBorderFlag(paramGraphics, paramInt++, i, "E", 8);
    drawBorderFlag(paramGraphics, paramInt++, i, "SE", 16);
    drawBorderFlag(paramGraphics, paramInt++, i, "S", 32);
    drawBorderFlag(paramGraphics, paramInt++, i, "SW", 64);
    drawBorderFlag(paramGraphics, paramInt++, i, "W", 128);
    drawBorderFlag(paramGraphics, paramInt++, i, "NW", 1);
    return paramInt;
  }

  private void drawBorderFlag(Graphics paramGraphics, int paramInt1, int paramInt2, String paramString, int paramInt3) {
    StringUtil.drawLine(paramGraphics, paramInt1, new StringBuilder().append(paramString).append(" Border: ").append((paramInt2 & paramInt3) == 0 ? "Clear" : "[red]Blocked").toString());
  }

  private String getBinaryString(int paramInt) {
    String str = Integer.toBinaryString(paramInt);
    StringBuilder localStringBuilder = new StringBuilder();
    int i = 32 - str.length();
    for (int j = 0; j < i; j++) {
      localStringBuilder.append('0');
    }
    localStringBuilder.append(str);
    return localStringBuilder.toString();
  }

  private void highlight(Graphics paramGraphics, RSTile paramRSTile, Color paramColor) {
    Point localPoint1 = this.calc.tileToScreen(paramRSTile, 0.0D, 0.0D, 0);
    Point localPoint2 = this.calc.tileToScreen(paramRSTile, 1.0D, 0.0D, 0);
    Point localPoint3 = this.calc.tileToScreen(paramRSTile, 0.0D, 1.0D, 0);
    Point localPoint4 = this.calc.tileToScreen(paramRSTile, 1.0D, 1.0D, 0);
    if ((localPoint3.x != -1) && (localPoint4.x != -1) && (localPoint2.x != -1) && (localPoint1.x != -1)) {
      paramGraphics.setColor(paramColor);
      paramGraphics.fillPolygon(new int[] { localPoint3.x, localPoint4.x, localPoint2.x, localPoint1.x }, new int[] { localPoint3.y, localPoint4.y, localPoint2.y, localPoint1.y }, 4);
    }
  }
}